package com.jacky.webflux.services.impl;

import cn.hutool.core.bean.BeanUtil;
import com.jacky.webflux.dtos.AppUserDto;
import com.jacky.webflux.entities.AppUserEntity;
import com.jacky.webflux.repositories.AppUserRepository;
import com.jacky.webflux.services.AppUserService;
import jakarta.annotation.Resource;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.r2dbc.core.R2dbcEntityTemplate;
import org.springframework.data.relational.core.query.Criteria;
import org.springframework.data.relational.core.query.Query;
import org.springframework.r2dbc.core.DatabaseClient;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.util.ArrayList;
import java.util.List;

@Service
public class AppUserServiceImpl implements AppUserService {

    @Resource
    private AppUserRepository appUserRepository;

    @Resource
    private R2dbcEntityTemplate r2dbcEntityTemplate;

    @Override
    public Mono<AppUserDto> getById(Long userId) {
        return appUserRepository.findById(userId)
                .map(user -> BeanUtil.toBean(user, AppUserDto.class));
    }

    @Override
    public Mono<AppUserDto> saveUser(AppUserDto dto) {
        return appUserRepository.save(BeanUtil.toBean(dto, AppUserEntity.class))
                .map(user -> BeanUtil.toBean(user, AppUserDto.class));
    }

    @Override
    public Mono<AppUserDto> updateById(Long id, AppUserDto dto) {
        AppUserEntity entity = BeanUtil.toBean(dto, AppUserEntity.class);
        entity.setId(id);
        return appUserRepository.save(entity)
                .map(user -> BeanUtil.toBean(user, AppUserDto.class));
    }

    @Override
    public Mono<Void> deleteById(Long userId) {
        return appUserRepository.deleteById(userId);
    }

    @Override
    public Flux<AppUserDto> getAllUsers() {
        PageRequest pr = PageRequest.of(1, 10);
        Flux<AppUserEntity> allWithPage = appUserRepository.findAllBy(pr);
        allWithPage.subscribe(System.out::println);
        System.out.println(pr);

        return appUserRepository.findAll()
                .map(user -> BeanUtil.toBean(user, AppUserDto.class));
    }

    @Override
    public Mono<List<AppUserDto>> allUserList() {
        return appUserRepository.findAll()
                .map(user -> BeanUtil.toBean(user, AppUserDto.class))
                .collectList()
                .defaultIfEmpty(new ArrayList<>());
    }

    @Override
    public Mono<Page<AppUserDto>> getWithPage(Pageable pageable) {
        return appUserRepository.findAllBy(pageable)
                .map(user -> BeanUtil.toBean(user, AppUserDto.class))
                .collectList()
                .zipWith(appUserRepository.count())
                .map(p -> new PageImpl<>(p.getT1(), pageable, p.getT2()));
    }
}
